package gui;

import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import config.ConfigManager;
import config.Constants;
import config.DatabaseConnectionPool;
import config.ReadAndWriteJson;
import handler.ExceptionMsgHandler;
import handler.PlcHandler;
import org.apache.commons.lang3.ArrayUtils;
import po.Data;
import sql.GetSql;
import sql.SQLInsertBuilder;
import task.TaskScheduler;
import task.UpdateLabelTask;
import utils.DateUtils;
import utils.EncryptionUtils;
import utils.StringUtils;
import utils.TCPUtils;
import utils.db.DatabaseConnectionTest;
import utils.tcp.ModbusTcpMaster;

import javax.sql.DataSource;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.sql.*;
import java.util.*;
import java.util.List;

import static config.Constants.plcDataLengths;
import static config.Constants.plcDataTypes;

public class DatabaseConnectionMain {
    // 新建日志记录
    private static final Logger logger = LoggerFactory.getLogger(DatabaseConnectionMain.class);
    // PLC连接
    public static ModbusMaster master;
    // 是否跳转界面相关
    public static boolean dbIsConnected = false;
    private static boolean plcIsConnected = false;
    // MySQL数据库配置相关
    private static String USER;
    private static String PASSWORD;
    private static String IP;
    private static String PORT;
    private static String DBTYPE;
    private static String URL;
    private static String DBNAME;
    private static String PLC_ADDRESS;
    private static String SLAVE_ID;
    private static String PLC_PORT;
    private static String FILENAME;
    private static UpdateLabelTask updateLabelTask;
    private static TaskScheduler taskScheduler;
    private static final Map<String, DataSource> connectionPool = new HashMap<>();
    private static Connection connection;

    // 通常的系统数据库名称列表，根据您的数据库服务器可能有所不同
    static String[] systemDatabases = {
            "information_schema", "mysql", "performance_schema", "sys"
    };
    // 错误框
    public static JTextArea exceptionTextArea = new JTextArea(5, 30);

    private static final boolean isDev = false;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(DatabaseConnectionMain::createAndShowDBGUI);
    }

    private static void createAndShowDBGUI() {
        JFrame frame = new JFrame("EasyPLC2DB Connect Tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 400); // 适当增加窗口大小
        CustomWindowIcon.setIcon(frame);

        // 主面板使用BorderLayout布局管理器
        JPanel mainPanel = new JPanel(new BorderLayout());

        // 标题
        JLabel titleLabel = new JLabel("EasyPLC2DB");
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        titleLabel.setFont(new Font("SansSerif", Font.BOLD, 30));
        // 将标题添加到NORTH，以便它出现在顶部
        mainPanel.add(titleLabel, BorderLayout.NORTH);

        JPanel dbPanel = createDbPanel(frame);
        mainPanel.add(dbPanel, BorderLayout.CENTER);

        JPanel plcPanel = createPlcPanel(frame);
        mainPanel.add(plcPanel, BorderLayout.EAST);

        frame.setContentPane(mainPanel);
        frame.pack(); // 根据组件preferred size调整窗口大小
        frame.setLocationRelativeTo(null); // 居中显示窗口
        frame.setVisible(true);
    }

    private static JPanel createPlcPanel(JFrame frame) {
        // 右侧PLC连接面板
        JPanel plcPanel = new JPanel(new GridBagLayout());
        GridBagConstraints plcConstraints = new GridBagConstraints();
        plcConstraints.anchor = GridBagConstraints.WEST;
        plcConstraints.insets = new Insets(5, 5, 5, 5);
        plcConstraints.fill = GridBagConstraints.HORIZONTAL;

        // PLC地址
        plcConstraints.gridx = 0;
        plcConstraints.gridy = 0;
        plcPanel.add(new JLabel("PLC Address:"), plcConstraints);

        plcConstraints.gridx = 1;
        JTextField plcAddressField = new JTextField(20);
        String plcAddress = StringUtils.isNullOrEmpty(ConfigManager.getPlcAddress()) ? "192.168.10.10" : ConfigManager.getPlcAddress();
        plcAddressField.setText(plcAddress);
        plcPanel.add(plcAddressField, plcConstraints);

        // plc port
        plcConstraints.gridx = 0;
        plcConstraints.gridy = 1;
        plcPanel.add(new JLabel("PLC Port:"), plcConstraints);

        plcConstraints.gridx = 1;
        JTextField plcPortField = new JTextField(5);
        String plcPort = StringUtils.isNullOrEmpty(ConfigManager.getPLCPort()) ? "502" : ConfigManager.getPLCPort();
        plcPortField.setText(plcPort);
        plcPanel.add(plcPortField, plcConstraints);


        // Slave ID
        plcConstraints.gridx = 0;
        plcConstraints.gridy = 2;
        plcPanel.add(new JLabel("Slave ID:"), plcConstraints);

        plcConstraints.gridx = 1;
        JTextField slaveIdField = new JTextField(5);
        String slaveId = StringUtils.isNullOrEmpty(ConfigManager.getSlavesId()) ? "1" : ConfigManager.getSlavesId();
        slaveIdField.setText(slaveId);
        plcPanel.add(slaveIdField, plcConstraints);

        // 测试PLC连接按钮
        JButton testPlcButton = new JButton("Test PLC Connection");
        plcConstraints.gridx = 1;
        plcConstraints.gridy = 3;
        plcConstraints.gridwidth = 2;
        plcConstraints.fill = GridBagConstraints.NONE;
        testPlcButton.addActionListener(e -> {
            // 测试PLC连接的逻辑
            try {
                // 测试环境
                if (isDev) {
                    master = TCPUtils.getMaster(plcAddressField.getText(), Integer.parseInt(slaveIdField.getText()));
                } else {
                    master = TCPUtils.getMaster(plcAddressField.getText(), Integer.valueOf(plcPortField.getText()));
                    TCPUtils.getPLCData(master, Integer.parseInt(slaveIdField.getText()), 1, DataType.TWO_BYTE_INT_UNSIGNED);
                }
            } catch (Exception ex) {
                logger.error("Failed to connect to PLC.", ex);
                JOptionPane.showMessageDialog(frame, "Failed to connect to PLC.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            // 此时如果数据库和PLC都链接成功，需要更换成另一个面板
            JOptionPane.showMessageDialog(frame, "Connection successful.", "Success", JOptionPane.INFORMATION_MESSAGE);
            plcIsConnected = true;
            PLC_ADDRESS = plcAddressField.getText();
            SLAVE_ID = slaveIdField.getText();
            PLC_PORT = plcPortField.getText();
            JumpNewInterface(frame);
        });
        plcPanel.add(testPlcButton, plcConstraints);
        return plcPanel;
    }

    private static void JumpNewInterface(JFrame frame) {
        if (plcIsConnected && dbIsConnected) {
            // 如果连接测试通过，弹窗提示是否需要保存
            try {
                FILENAME = IP + "_" + USER + "_" + EncryptionUtils.encrypt(PASSWORD);
            } catch (Exception e) {
                logger.error("Failed to encrypt password.", e);
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, e);
            }
            int result = JOptionPane.showConfirmDialog(frame, "是否确定保存登录信息？", "保存登录信息", JOptionPane.YES_NO_OPTION);
            if (result == 0) {

                /*
                // 用户选择“是”，弹出文件夹选择器让用户选择保存地址
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); // 设置为文件夹选择模式
                fileChooser.setCurrentDirectory(new File(System.getProperty("user.home"))); // 设置默认目录为用户主目录

                int fileChooserResult = fileChooser.showSaveDialog(frame);
                if (fileChooserResult == JFileChooser.APPROVE_OPTION) {
                    File selectedFolder = fileChooser.getSelectedFile();
                    // 这里可以添加保存登录信息到文件夹的代码
                    JOptionPane.showMessageDialog(
                            frame,
                            "登录信息将保存到：" + selectedFolder.getAbsolutePath(),
                            "保存成功",
                            JOptionPane.INFORMATION_MESSAGE
                    );
                }*/

                // PLC相关
                ConfigManager.setProperty("PLC_ADDRESS", PLC_ADDRESS);
                ConfigManager.setProperty("SLAVES_ID", SLAVE_ID);
                ConfigManager.setProperty("PLC_PORT", PLC_PORT);
                // DB相关
                ConfigManager.setProperty("DB_IP", IP);
                ConfigManager.setProperty("DB_PORT", PORT);
                ConfigManager.setProperty("DB_USER", USER);
                try {
                    ConfigManager.setProperty("DB_PASSWORD", EncryptionUtils.encrypt(PASSWORD));
                } catch (Exception e) {
                    logger.error("Failed to encrypt password.", e);
                }
                ConfigManager.setProperty("DB_TYPE", DBTYPE);
            }
            // 关闭当前窗口
            frame.dispose();
            // 创建并显示新界面
            openNewInterface();
        }
    }

    private static JPanel createDbPanel(JFrame frame) {
        JPanel dbPanel = new JPanel(new GridBagLayout());
        dbPanel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();

        // 初始化约束条件
        constraints.anchor = GridBagConstraints.WEST; // 左对齐
        constraints.insets = new Insets(5, 5, 5, 5); // 组件边距
        constraints.fill = GridBagConstraints.HORIZONTAL; // 水平填充

        // 下拉框
        constraints.gridx = 0;
        constraints.gridy = 1;
        dbPanel.add(new JLabel("Select Database Type:"), constraints);

        constraints.gridx = 1;
        JComboBox<String> dbTypeComboBox = new JComboBox<>(new String[]{"", "MySQL", "PostgreSQL", "SQLite"});
        if (!StringUtils.isNullOrEmpty(ConfigManager.getDbType())) {
            dbTypeComboBox.setSelectedItem(ConfigManager.getDbType());
        }
        dbPanel.add(dbTypeComboBox, constraints);

        // 连接地址
        constraints.gridx = 0;
        constraints.gridy = 2;
        dbPanel.add(new JLabel("Connection IP:"), constraints);

        constraints.gridx = 1;
        constraints.gridy = 2;
        JTextField addressField = new JTextField(20); // 设置列数
        String address = StringUtils.isNullOrEmpty(ConfigManager.getDbIp()) ? "localhost" : ConfigManager.getDbIp();
        addressField.setText(address);
        dbPanel.add(addressField, constraints);

        // 端口
        constraints.gridx = 0;
        constraints.gridy = 3;
        dbPanel.add(new JLabel("Port:"), constraints);

        constraints.gridx = 1;
        JTextField portField = new JTextField(5); // 设置较短的列数适应端口号长度
        String port = StringUtils.isNullOrEmpty(ConfigManager.getDbPort()) ? "3306" : ConfigManager.getDbPort();
        portField.setText(port);
        dbPanel.add(portField, constraints);

        // 用户名
        constraints.gridx = 0;
        constraints.gridy = 4;
        dbPanel.add(new JLabel("Username:"), constraints);

        constraints.gridx = 1;
        JTextField userField = new JTextField(20);
        String user = StringUtils.isNullOrEmpty(ConfigManager.getDbUser()) ? "root" : ConfigManager.getDbUser();
        userField.setText(user);
        dbPanel.add(userField, constraints);

        // 密码
        constraints.gridx = 0;
        constraints.gridy = 5;
        dbPanel.add(new JLabel("Password:"), constraints);

        constraints.gridx = 1;
        JPasswordField passwordField = new JPasswordField(20);
        String password = null;
        try {
            password = StringUtils.isNullOrEmpty(ConfigManager.getDbPassword()) ? "root" :
                    EncryptionUtils.decrypt(ConfigManager.getDbPassword());
        } catch (Exception e) {
            logger.error("Failed to decrypt password.", e);
        }
        passwordField.setText(password);
        dbPanel.add(passwordField, constraints);

        // 测试连接按钮
        JButton testButton = new JButton("Test Connection");
        constraints.gridx = 1;
        constraints.gridy = 6;
        constraints.gridwidth = 2;
        constraints.fill = GridBagConstraints.NONE; // 不填充
        testButton.addActionListener(e -> {
            if (dbTypeComboBox.getSelectedIndex() <= 0) {
                JOptionPane.showMessageDialog(frame, "Please select a database type.", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            // 测试连接逻辑
            if (dbTypeComboBox.getSelectedIndex() == 1) {
                // MySQL -- 调用方法
                boolean b = DatabaseConnectionTest.testConnection(addressField.getText(), portField.getText(), userField.getText(), new String(passwordField.getPassword()));
                if (b) {
                    JOptionPane.showMessageDialog(frame, "Connection successful.", "Success", JOptionPane.INFORMATION_MESSAGE);
                    dbIsConnected = true;
                    // 保存当前数据库连接信息
                    IP = addressField.getText();
                    PORT = portField.getText();
                    USER = userField.getText();
                    URL = "jdbc:mysql://" + IP + ":" + PORT + "/";
                    PASSWORD = new String(passwordField.getPassword());
                    DBTYPE = Objects.requireNonNull(dbTypeComboBox.getSelectedItem()).toString();
                    JumpNewInterface(frame);
                } else {
                    JOptionPane.showMessageDialog(frame, "Connection failed.", "Error", JOptionPane.ERROR_MESSAGE);
                }
            } else if (dbTypeComboBox.getSelectedIndex() == 2) {
                // PostgreSQL -- 暂不支持 -- 返回信息
                JOptionPane.showMessageDialog(frame, "PostgreSQL is not supported yet.", "Error", JOptionPane.ERROR_MESSAGE);

            } else if (dbTypeComboBox.getSelectedIndex() == 3) {
                // SQLite -- 暂不支持 -- 返回信息
                JOptionPane.showMessageDialog(frame, "SQLite is not supported yet.", "Error", JOptionPane.ERROR_MESSAGE);
            }
        });
        dbPanel.add(testButton, constraints);
        return dbPanel;
    }

    // 打开新界面的方法
    private static void openNewInterface() {
        JFrame newFrame = new JFrame("Easy PLC Data To DB 测试版V1.3  本软件仅供内部学习使用");
        newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        CustomWindowIcon.setIcon(newFrame);

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 判断当前用户名是否存在配置文件
        Properties name = ConfigManager.getProperties("name");
        Data datas;
        if (name != null) {
            // 判断当前用户名是否存在配置文件
            String property = name.getProperty(FILENAME);
            if (property != null) {
                // 读取配置文件
                datas = ReadAndWriteJson.readJson(property);
            } else {
                datas = null;
            }
        } else {
            datas = null;
        }

        // Left Panel: Database and Control
        JPanel leftPanel = new JPanel(new BorderLayout());
        leftPanel.setBorder(createPanelBorder("选择控制与异常"));

        // Database and Table Selection Panel
        JPanel dbTablePanel = new JPanel();
        dbTablePanel.setLayout(new BoxLayout(dbTablePanel, BoxLayout.Y_AXIS));
        dbTablePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // Database Selection Panel
        JPanel dbPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel dbLabel = new JLabel("选择数据库： ");
        String[] databases = getDatabases();
        JComboBox<String> dbComboBox = new JComboBox<>(databases);
        // 存在保存文件则回显
        if (datas != null) {
            dbComboBox.setSelectedItem(datas.getDbName());
            // 更新全局变量
            DBNAME = datas.getDbName();

        }
        dbPanel.add(dbLabel);
        dbPanel.add(dbComboBox);
        dbTablePanel.add(dbPanel);

        // Table Selection Panel
        JPanel tablePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel tableLabel = new JLabel("选择数据表： ");
        JComboBox<String> tableComboBox = new JComboBox<>();
        tableComboBox.setPreferredSize(new Dimension(150, 30));
        // 存在保存文件则回显
        if (datas != null) {
            // 查询获取数据表
            String[] tables = getTablesFromDatabase(datas.getDbName());
            tableComboBox.removeAllItems();
            for (String table : tables) {
                tableComboBox.addItem(table);
            }
            tableComboBox.setSelectedItem(datas.getTableName());
        }
        tablePanel.add(tableLabel);
        tablePanel.add(tableComboBox);
        dbTablePanel.add(tablePanel);

        // ActionListener for dbComboBox
        dbComboBox.addActionListener(e -> {
            String selectedDb = (String) dbComboBox.getSelectedItem();
            DBNAME = selectedDb;
            if (selectedDb != null) {
                // Call method to get tables for the selected database
                String[] tables = getTablesFromDatabase(selectedDb);

                // Clear current items in tableComboBox
                tableComboBox.removeAllItems();

                // Add retrieved tables to tableComboBox
                for (String table : tables) {
                    tableComboBox.addItem(table);
                }
            }
        });

        // Control Panel: Collection Frequency, Time, Status
        JPanel controlPanel = new JPanel();
        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.Y_AXIS));

        // Collection Frequency Panel
        JPanel frequencyPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel frequencyLabel = new JLabel("采集频率：    ");
        JTextField hoursField = new JTextField(2);
        JLabel hoursLabel = new JLabel("小时");
        hoursField.setText("0");
        JTextField minutesField = new JTextField(2);
        JLabel minutesLabel = new JLabel("分钟");
        minutesField.setText("0");
        JTextField secondsField = new JTextField(2);
        JLabel secondsLabel = new JLabel("秒");
        secondsField.setText("0");
        JTextField millisecondsField = new JTextField(3);
        JLabel millisecondsLabel = new JLabel("毫秒");
        millisecondsField.setText("10");
        frequencyPanel.add(frequencyLabel);
        frequencyPanel.add(hoursField);
        frequencyPanel.add(hoursLabel);
        frequencyPanel.add(minutesField);
        frequencyPanel.add(minutesLabel);
        frequencyPanel.add(secondsField);
        frequencyPanel.add(secondsLabel);
        frequencyPanel.add(millisecondsField);
        frequencyPanel.add(millisecondsLabel);
        controlPanel.add(frequencyPanel);

        // 配置文件若存在覆盖初始值
        if (datas != null) {
            hoursField.setText(datas.getFreqHour().toString());
            minutesField.setText(datas.getFreqMinute().toString());
            secondsField.setText(datas.getFreqSecond().toString());
            millisecondsField.setText(datas.getFreqMinSecond().toString());
        }

        // 添加额外的空白区域来调整上下边距
        JPanel emptyPanel5 = new JPanel();
        emptyPanel5.setPreferredSize(new Dimension(5, 5)); // 设置空白区域的大小
        controlPanel.add(emptyPanel5);

        // Collection Time Panel
        JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel timeLabel = new JLabel("采集时间：    ");
        JLabel timeValueLabel = new JLabel("00 小时 00 分钟 00 秒");
        if (datas != null) {
            timeValueLabel.setText(datas.getTime());
        }
        timePanel.add(timeLabel);
        timePanel.add(timeValueLabel);
        controlPanel.add(timePanel);

        controlPanel.add(emptyPanel5);

        // Collection Status Panel
        JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel statusLabel = new JLabel("采集状态：    ");
        JLabel statusValueLabel = new JLabel("未开始采集");
        statusPanel.add(statusLabel);
        statusPanel.add(statusValueLabel);
        controlPanel.add(statusPanel);


        // 创建异常信息面板
        JPanel exceptionPanel = new JPanel(new GridBagLayout());
        exceptionPanel.setBorder(BorderFactory.createTitledBorder("异常信息")); // 设置标题为异常信息

        // 创建异常信息显示框 JTextArea
        //exceptionTextArea = new JTextArea(5, 30); // 设置行数和列数
        exceptionTextArea.setEditable(false); // 设置为不可编辑，仅用于显示
        exceptionTextArea.setLineWrap(true); // 自动换行
        JScrollPane scrollPane = new JScrollPane(exceptionTextArea); // 添加滚动条

        // GridBagConstraints 设置
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(15, 10, 5, 10); // 调整上下左右的边距

        // 添加额外的空白区域来调整上下边距
        JPanel emptyPanel = new JPanel();
        emptyPanel.setPreferredSize(new Dimension(10, 10)); // 设置空白区域的大小
        controlPanel.add(emptyPanel);

        // 查看是否存在保存文件
        if (datas != null) {
            if (datas.getErrorMessages() != null) {
                exceptionTextArea.setText(datas.getErrorMessages());
            }
        }

        // 将异常信息显示框添加到异常信息面板中
        exceptionPanel.add(scrollPane, gbc);

        // 将异常信息面板添加到主面板中
        controlPanel.add(exceptionPanel);


        dbTablePanel.add(controlPanel);
        leftPanel.add(dbTablePanel, BorderLayout.CENTER);
        mainPanel.add(leftPanel, BorderLayout.WEST);

        // Center Panel: Display Field Information Table
        JPanel centerPanel = new JPanel(new BorderLayout());
        centerPanel.setBorder(createPanelBorder("字段信息表格"));

        String[] columnNames = {"字段名称", "类型", "注释", "必填", "PLC数据类型", "地址长度", "PLC起始地址", "默认值"};
        DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) {
            @Override
            public boolean isCellEditable(int row, int column) {
                if (column == 5) {
                    try {
                        int length = (int) getValueAt(row, 5); // Get current length value
                        return length == -1; // Allow editing only if length is 0
                    } catch (Exception e) {
                        return false;
                    }
                }
                // 设置前四列不可编辑
                return column >= 4;  // 只有索引大于等于4的列可编辑
            }
        };
        JTable fieldTable = new JTable(tableModel);
        fieldTable.setRowHeight(30);
        fieldTable.getTableHeader().setFont(new Font("SansSerif", Font.BOLD, 14));

        // 创建PLC数据类型列的单元格编辑器为JComboBox
        TableColumn plcDataTypeColumn = fieldTable.getColumnModel().getColumn(4);
        JComboBox<String> comboBox = new JComboBox<>(plcDataTypes);
        plcDataTypeColumn.setCellEditor(new DefaultCellEditor(comboBox));

        // Custom cell renderer to display length in Length column based on selection
        TableColumn lengthColumn = fieldTable.getColumnModel().getColumn(5);
        lengthColumn.setCellRenderer(new LengthCellRenderer(plcDataTypes, plcDataLengths));

        // Add ActionListener to JComboBox to update Length column
        comboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JComboBox<String> combo = (JComboBox<String>) e.getSource();
                int selectedRow = fieldTable.getSelectedRow();
                if (selectedRow != -1) {
                    String selectedType = (String) combo.getSelectedItem();
                    if (selectedType == null || selectedType.equals("")) {
                        fieldTable.setValueAt("", selectedRow, 5);
                        return;
                    }
                    int length = getLengthForDataType(selectedType, plcDataTypes, plcDataLengths);
                    fieldTable.setValueAt(length, selectedRow, 5); // Update Length column
                }
            }
        });


        int[] columnWidths = {150, 120, 200, 90, 150, 100, 150, 100};
        for (int i = 0; i < columnNames.length; i++) {
            fieldTable.getColumnModel().getColumn(i).setPreferredWidth(columnWidths[i]);
        }

        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment(JLabel.CENTER);
        for (int i = 0; i < fieldTable.getColumnCount(); i++) {
            fieldTable.getColumnModel().getColumn(i).setCellRenderer(centerRenderer);
        }

        JScrollPane fieldScrollPane = new JScrollPane(fieldTable);
        fieldScrollPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        centerPanel.add(fieldScrollPane, BorderLayout.CENTER);
        mainPanel.add(centerPanel, BorderLayout.CENTER);

        try {
            if (datas != null) {
                List<FieldInfo> fields = getFieldsFromTable(datas.getTableName());
                tableModel.setRowCount(0);
                for (int i = 0; i < fields.size(); i++) {
                    Data.dataList list = datas.getPlcData().get(datas.getTableName());
                    int type = getLengthForDataType(list.getPlcDataTypes().get(i).toString(), plcDataTypes, plcDataLengths);
                    Object[] row = {
                            fields.get(i).getName(),
                            fields.get(i).getType(),
                            fields.get(i).getComment(),
                            fields.get(i).getRequired() ? "是" : "否",
                            list.getPlcDataTypes().get(i),
                            type == 0 ? "" : type,
                            list.getPlcAddresses().get(i),
                            list.getDefaultValue().get(i)
                    };
                    tableModel.addRow(row);
                }
            }
        } catch (Exception e) {
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, e, "-历史数据读取失败");
        }

        // ActionListener for tableComboBox
        tableComboBox.addActionListener(e -> {
            String selectedTable = (String) tableComboBox.getSelectedItem();
            if (selectedTable != null) {
                // Call method to get fields for the selected table
                List<FieldInfo> fields = getFieldsFromTable(selectedTable);
                // Clear current data in tableModel
                tableModel.setRowCount(0);

                if (datas != null && datas.getPlcData().containsKey(selectedTable)) {
                    Data.dataList list = datas.getPlcData().get(selectedTable);
                    for (int i = 0; i < fields.size(); i++) {
                        int type = getLengthForDataType(list.getPlcDataTypes().get(i).toString(), plcDataTypes, plcDataLengths);
                        Object[] row = {
                                fields.get(i).getName(),
                                fields.get(i).getType(),
                                fields.get(i).getComment(),
                                fields.get(i).getRequired() ? "是" : "否",
                                list.getPlcDataTypes().get(i),
                                type == 0 ? "" : type,
                                list.getPlcAddresses().get(i),
                                list.getDefaultValue().get(i)
                        };
                        tableModel.addRow(row);
                    }
                } else {
                    // Add retrieved fields to tableModel
                    for (FieldInfo field : fields) {
                        Object[] row = {
                                field.getName(),
                                field.getType(),
                                field.getComment(),
                                field.getRequired() ? "是" : "否",
                                "",
                                ""
                        };
                        tableModel.addRow(row);
                    }
                }
            }
        });

        // Right Bottom Button Panel
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.setBorder(createPanelBorder("操作按钮"));

        // Clean Button
        JButton cleanErrorButton = new JButton("清除报警内容");
        cleanErrorButton.addActionListener(e -> {
                    if (JOptionPane.showConfirmDialog(newFrame, "确定要清除报警内容吗？", "确认", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                        exceptionTextArea.setText(null);
                    }
                }
        );
        buttonPanel.add(cleanErrorButton);

        // Clean Button
        JButton cleanButton = new JButton("清除本页内容");
        cleanButton.addActionListener(e -> {
                    String selectedTable = (String) tableComboBox.getSelectedItem();
                    if (JOptionPane.showConfirmDialog(newFrame, "确定要清除本页内容吗？", "确认", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                        if (datas != null) {
                            datas.getPlcData().remove(selectedTable);
                        }
                        // 重新渲染结果
                        tableComboBox.actionPerformed(e);
                    }
                }
        );
        buttonPanel.add(cleanButton);

        // Save Button
        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> {
            // 弹窗提示是否确定保存
            if (JOptionPane.showConfirmDialog(newFrame, "确定要保存吗？", "确认", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                // 查询name.properties判断是否存在key -> IP_USER_PASSWORD 存在则进行覆盖 不存在则新建并保存在name.properties
                Properties names = ConfigManager.getProperties("name");
                try {
                    // 重新获取
                    FILENAME = IP + "_" + USER + "_" + EncryptionUtils.encrypt(PASSWORD);
                } catch (Exception ex) {
                    // 弹窗提示保存失败
                    JOptionPane.showMessageDialog(newFrame, "保存失败", "错误", JOptionPane.ERROR_MESSAGE);
                    ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                    logger.error(ex.getMessage());
                    return;
                }
                String fileName = null;
                if (names != null) {
                    fileName = names.getProperty(FILENAME) == null ? StringUtils.generateRandomString(16) : names.getProperty(FILENAME);
                } else {
                    fileName = StringUtils.generateRandomString(16);
                }

                // 遍历表格模型获取数据
                int rowCount = tableModel.getRowCount();
                int columnCount = tableModel.getColumnCount();
                List plcDataTypes = new ArrayList();
                List plcAddresses = new ArrayList();
                List plcDefaultValues = new ArrayList();
                for (int row = 0; row < rowCount; row++) {
                    Object[] rowData = new Object[columnCount];
                    for (int column = 0; column < columnCount; column++) {
                        rowData[column] = tableModel.getValueAt(row, column);
                    }
                    // 现在处理rowData，这是表格中当前行的数据数组
                    plcDataTypes.add(rowData[4]);
                    plcAddresses.add(rowData[6]);
                    plcDefaultValues.add(rowData[7]);

                }
                // 获取当前选中的表名
                Data data = new Data();
                data.setDbName(DBNAME);
                data.setErrorMessages(exceptionTextArea.getText());
                data.setFreqHour(Integer.parseInt(hoursField.getText()));
                data.setFreqMinute(Integer.parseInt(minutesField.getText()));
                data.setFreqSecond(Integer.parseInt(secondsField.getText()));
                data.setFreqMinSecond(Integer.parseInt(millisecondsField.getText()));
                data.setTableName(Objects.requireNonNull(tableComboBox.getSelectedItem()).toString());
                Data.dataList list = new Data.dataList();
                list.setPlcDataTypes(plcDataTypes);
                list.setPlcAddresses(plcAddresses);
                list.setDefaultValue(plcDefaultValues);
                if (datas != null) {
                    data.setPlcData(datas.getPlcData());
                }
                data.getPlcData().put(data.getTableName(), list);
                data.setTime(timeValueLabel.getText());
                if (ReadAndWriteJson.writeJson(data, fileName)) {
                    // 写入name.properties中
                    ConfigManager.setProperties(FILENAME, fileName);
                    JOptionPane.showMessageDialog(newFrame, "保存成功！");
                } else {
                    JOptionPane.showMessageDialog(newFrame, "保存失败！");
                }
            }
        });
        buttonPanel.add(saveButton);

        // Close Button
        JButton closeButton = new JButton("退出至登陆页");
        closeButton.addActionListener(e -> {
            newFrame.dispose(); // Close the JFrame
            createAndShowDBGUI();
            dbIsConnected = false;
            plcIsConnected = false;
        });
        buttonPanel.add(closeButton);

        // 单次 Button
        JButton collectSingleButton = new JButton("单次采集");
        collectSingleButton.addActionListener(e -> {
            // 首先进行列表数据提取
            // 遍历表格模型获取数据
            int rowCount = tableModel.getRowCount();
            int columnCount = tableModel.getColumnCount();
            List<String> plcDataTypes = new ArrayList<>();
            List<String> plcAddresses = new ArrayList<>();
            List<String> columnNameList = new ArrayList<>();
            List<String> lengthColumnList = new ArrayList<>();
            List<String> defoautList = new ArrayList<>();

            for (int row = 0; row < rowCount; row++) {
                Object[] rowData = new Object[columnCount];
                for (int column = 0; column < columnCount; column++) {
                    rowData[column] = tableModel.getValueAt(row, column);
                }
                // 如果出现必填项未绑定，抛出错误框
                if ("是".equals(rowData[3]) && !rowData[1].toString().contains("time")) {
                    if (StringUtils.isNullOrEmpty(rowData[4])) {
                        JOptionPane.showMessageDialog(newFrame, "必填项未绑定，请检查！");
                        return;
                    }
                }
                // 填写地址但是没有填写类型报错
                if (!StringUtils.isNullOrEmpty(rowData[6]) && StringUtils.isNullOrEmpty(rowData[4])) {
                    JOptionPane.showMessageDialog(newFrame, "类型未完整填写，请检查！");
                    return;
                }
                // 只保存绑定了PLC地址或填写默认值的
                if (!StringUtils.isNullOrEmpty(rowData[6]) || !StringUtils.isNullOrEmpty(rowData[7])) {
                    try {
                        // 选择类型为数组但是没有填长度抛出异常
                        if (rowData[4] != null && (rowData[4].toString().equals("FLOAT[ ]")
                                || rowData[4].toString().equals("LONG0[ ]"))
                                && (Objects.equals(rowData[5].toString(), "-1")
                                || Objects.equals(rowData[5].toString(), "0"))) {
                            JOptionPane.showMessageDialog(newFrame, "数组类型采集长度不能为-1！");
                            return;
                        }
                        columnNameList.add(rowData[0] == null ? null : rowData[0].toString());
                        plcDataTypes.add(rowData[4] == null ? null : rowData[4].toString());
                        lengthColumnList.add(rowData[5] == null ? null : rowData[5].toString());
                        plcAddresses.add(rowData[6] == null ? null : rowData[6].toString());
                        defoautList.add(rowData[7] == null ? null : rowData[7].toString());
                    } catch (Exception ex) {
                        ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                        return;
                    }
                }
            }
            // 新建数据库连接
            if (connectionPool.get(DBNAME) == null) {
                connectionPool.put(DBNAME, DatabaseConnectionPool.createConnectionPool(URL + DBNAME, USER, PASSWORD));
            }
            try {
                connection = connectionPool.get(DBNAME).getConnection();
            } catch (SQLException ex) {
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                throw new RuntimeException(ex);
            }
            String selectedDb = (String) dbComboBox.getSelectedItem();
            String selectedTable = (String) tableComboBox.getSelectedItem();
            if (plcAddresses.size() == 0 || plcDataTypes.size() == 0 || plcAddresses.size() != plcDataTypes.size()) {
                // 抛出提示填写
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, new Exception("请填写PLC地址和数据类型!"));
                return;
            }
            Object[] result = new Object[0];
            try {
                result = PlcHandler.getPLCAndArrayData(master, Integer.valueOf(SLAVE_ID), plcAddresses, plcDataTypes, lengthColumnList);
            } catch (Exception ex) {
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex, "-数据采集报错!");
                return;
            }
            String sql = SQLInsertBuilder.buildSingleInsertSQL(selectedDb, selectedTable, columnNameList, defoautList, result);
            logger.info("sql-->" + sql);

            try {
                Statement statement = connection.createStatement();
                statement.execute(sql);
                statement.close();
            } catch (SQLException ex) {
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                return;
            } finally {
                try {
                    connection.close();
                } catch (SQLException ex) {
                    logger.error("关闭数据库连接失败！", ex);
                    ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                }
            }
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, new Exception("单次采集完成!"));
        });
        buttonPanel.add(collectSingleButton);

        // Start Collection Button (Existing Button)
        JButton startCollectionButton = new JButton("单表采集");
        startCollectionButton.addActionListener(e -> {
            String selectedDb = (String) dbComboBox.getSelectedItem();
            String selectedTable = (String) tableComboBox.getSelectedItem();

            try {
                int hours = Integer.parseInt(hoursField.getText());
                int minutes = Integer.parseInt(minutesField.getText());
                int seconds = Integer.parseInt(secondsField.getText());
                int milliseconds = Integer.parseInt(millisecondsField.getText());
                long collectionFrequencyInMillis = ((hours * 60 + minutes) * 60 + seconds) * 1000 + milliseconds;

                JOptionPane.showMessageDialog(newFrame, "开始采集");
                // 首先进行列表数据提取
                // 遍历表格模型获取数据
                int rowCount = tableModel.getRowCount();
                int columnCount = tableModel.getColumnCount();
                List<String> plcDataTypes = new ArrayList<>();
                List<String> plcAddresses = new ArrayList<>();
                List<String> columnNameList = new ArrayList<>();
                List<String> columnLenList = new ArrayList<>();
                List<String> defaultList = new ArrayList<>();

                for (int row = 0; row < rowCount; row++) {
                    Object[] rowData = new Object[columnCount];
                    for (int column = 0; column < columnCount; column++) {
                        rowData[column] = tableModel.getValueAt(row, column);
                    }
                    // 如果出现必填项未绑定，抛出错误框
                    if ("是".equals(rowData[3]) && !rowData[1].toString().contains("time")) {
                        if (StringUtils.isNullOrEmpty(rowData[4].toString())) {
                            JOptionPane.showMessageDialog(newFrame, "必填项未绑定，请检查！");
                            return;
                        }
                    }
                    // 填写地址但是没有填写类型报错
                    if (!StringUtils.isNullOrEmpty(rowData[6]) && StringUtils.isNullOrEmpty(rowData[4])) {
                        JOptionPane.showMessageDialog(newFrame, "必填项未绑定，请检查！");
                        return;
                    }
                    // 如果类型是数组类型，抛出错误
                    if ("FLOAT[ ]".equals(rowData[4].toString()) || "LONG[ ]".equals(rowData[4].toString())) {
                        JOptionPane.showMessageDialog(newFrame, "数组类型暂只支持单次采集！");
                        return;
                    }
                    // 只保存绑定了PLC地址的
                    if (!StringUtils.isNullOrEmpty(rowData[6])) {
                        try {
                            columnNameList.add(rowData[0].toString());
                            plcDataTypes.add(rowData[4].toString());
                            plcAddresses.add(rowData[6].toString());
                            columnLenList.add(rowData[5].toString());
                            defaultList.add(rowData[7] == null ? null : rowData[7].toString());
                        } catch (Exception ex) {
                            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                            return;
                        }
                    }
                }

                // 开启采集任务
                if (taskScheduler != null) {
                    taskScheduler.shutdown();
                }
                taskScheduler = new TaskScheduler();

                if (connectionPool.get(DBNAME) == null) {
                    connectionPool.put(DBNAME, DatabaseConnectionPool.createConnectionPool(URL + DBNAME, USER, PASSWORD));
                }
                connection = connectionPool.get(DBNAME).getConnection();

                String sql = SQLInsertBuilder.buildSingleInsertSQL(selectedDb, selectedTable, columnNameList); // 预编译SQL
                PreparedStatement statement = connection.prepareStatement(sql);

                taskScheduler.startPeriodicTask(() -> {
                    try {
                        PlcHandler.getPLCData(master, Integer.valueOf(SLAVE_ID), plcAddresses, plcDataTypes, columnLenList, defaultList, statement);
                        statement.executeBatch();
                    } catch (Exception ex) {
                        ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                    } finally {
                        try {
                            statement.clearBatch();
                            statement.clearParameters();
                        } catch (SQLException ex) {
                            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                        }
                    }
                }, collectionFrequencyInMillis);

            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(newFrame, "请输入有效的数字。");
                return;
            } catch (SQLException ex) {
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
                return;
            }

            // 确定可以写入数据库后，开始记录采集时间
            if (updateLabelTask != null) {
                updateLabelTask.stopUpdating();
            }
            updateLabelTask = new UpdateLabelTask(timeValueLabel);
            updateLabelTask.startUpdating();
            // 修改采集状态为正在采集
            statusValueLabel.setText("正在采集");
            // 增加信息提示
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, new Exception("开始数据采集，当前采集表：" + tableComboBox.getSelectedItem()));
        });
        buttonPanel.add(startCollectionButton);

        // Start All Collection Button (Existing Button)
        JButton startAllCollectionButton = new JButton("多表采集");
        startAllCollectionButton.addActionListener(e -> {
            JOptionPane.showMessageDialog(newFrame, "正在开发");
        });
        buttonPanel.add(startAllCollectionButton);

        // Start All Collection Button (Existing Button)
        JButton stopAllCollectionButton = new JButton("停止采集");
        stopAllCollectionButton.addActionListener(e -> {
            // 关闭数据库连接
            try {
                connection.close();
            } catch (SQLException ex) {
                ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, ex);
            }
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, new Exception("数据库连接已关闭!"));
            // 关闭执行计划
            taskScheduler.shutdown();
            updateLabelTask.stopUpdating();
            // 修改采集状态为未采集
            statusValueLabel.setText("停止采集");
            // 增加信息提示
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, new Exception("数据采集已停止!"));
            JOptionPane.showMessageDialog(newFrame, "成功停止采集");
        });
        buttonPanel.add(stopAllCollectionButton);

        mainPanel.add(buttonPanel, BorderLayout.SOUTH);

        JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
        mainPanel.add(separator, BorderLayout.NORTH);

        newFrame.add(mainPanel);
        newFrame.setSize(1200, 800);
        newFrame.setLocationRelativeTo(null);
        newFrame.setVisible(true);

        // 添加窗口关闭监听器
        newFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 设置不关闭窗口，由监听器处理
        newFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int confirmExit = JOptionPane.showConfirmDialog(
                        newFrame,
                        "您确定要退出吗？",
                        "退出确认",
                        JOptionPane.YES_NO_CANCEL_OPTION,
                        JOptionPane.QUESTION_MESSAGE
                );
                switch (confirmExit) {
                    case JOptionPane.YES_OPTION:
                        // 执行保存设置的代码
                        saveButton.doClick();
                        // 关闭窗口和退出应用程序
                        newFrame.dispose(); // 关闭窗口
                        System.exit(0); // 退出应用程序
                        break;
                    case JOptionPane.NO_OPTION:
                        // 用户选择“否”，不执行任何操作，即不退出
                        break;
                    case JOptionPane.CANCEL_OPTION:
                        // 用户选择“取消”，不执行任何操作，即取消退出操作
                        break;
                    default:
                        // 可选：处理其他可能的情况
                        break;
                }
            }
        });
        newFrame.setVisible(true);
    }


    // 创建带标题的边框
    private static CompoundBorder createPanelBorder(String title) {
        return BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder(title),
                BorderFactory.createEmptyBorder(10, 10, 10, 10)
        );
    }

    public static String[] getDatabases() {
        String[] databases = new String[0];
        String sql = "SHOW DATABASES";
        try (Connection conn = DriverManager.getConnection(URL + "mysql", USER, PASSWORD)) {
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            ArrayList<String> list = new ArrayList<>();
            list.add("");
            while (rs.next()) {
                // 过滤系统数据库
                String db = rs.getString(1);
                if (!ArrayUtils.contains(systemDatabases, db)) {
                    list.add(db);
                }
            }
            databases = list.toArray(new String[0]);

        } catch (SQLException e) {
            ExceptionMsgHandler.addExceptionMsg(exceptionTextArea, e, "请退出重新登陆!");
        }
        return databases;
    }

    public static String[] getTablesFromDatabase(String dbName) {
        String[] tables = new String[0];
        String sql = "SHOW TABLES";
        try (Connection conn = DriverManager.getConnection(URL + dbName, USER, PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {

            ArrayList<String> list = new ArrayList<>();
            while (rs.next()) {
                list.add(rs.getString(1));
            }
            tables = list.toArray(new String[0]);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return tables;
    }

    // 获取表中字段信息列表的方法
    private static List<FieldInfo> getFieldsFromTable(String tableName) {
        List<FieldInfo> fieldInfos = new ArrayList<>();

        try (Connection conn = DriverManager.getConnection(URL + DBNAME, USER, PASSWORD);
             Statement stmt = conn.createStatement()) {

            // 对于MySQL，查询表的PRI字段，判断是否是主键
            String sql2 = GetSql.selectTablePRISql(DBNAME, tableName);
            ResultSet rs2 = stmt.executeQuery(sql2);
            String columnName = null;
            while (rs2.next()) {
                columnName = rs2.getString("COLUMN_NAME");
            }

            // 对于MySQL，使用SHOW COLUMNS FROM语句
            String sql = GetSql.selectTableColumnSql(DBNAME, tableName);
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                String name = rs.getString("column_name"); // 列名
                String type = rs.getString("column_type"); // 列类型
                String isNull = rs.getString("is_nullable"); // 是否可为空
                String comment = rs.getString("column_comment"); // 列注释

                if (Objects.equals(name, columnName)) {
                    continue;
                }
                // 根据查询结果构建FieldInfo对象
                FieldInfo fieldInfo = new FieldInfo(
                        name,
                        type,
                        comment,
                        "", // plcAddress 留空或根据实际逻辑填充
                        isNull.equalsIgnoreCase("NO") // 判断是否必填
                );
                fieldInfos.add(fieldInfo);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return fieldInfos;
    }

    // 定义字段信息的类
    private static class FieldInfo {
        String name;
        String type;
        String comment;
        String plcAddress;
        Boolean isRequired;

        public FieldInfo(String name, String type, String comment, String plcAddress, Boolean isRequired) {
            this.name = name;
            this.type = type;
            this.comment = comment;
            this.plcAddress = plcAddress;
            this.isRequired = isRequired;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        public String getPlcAddress() {
            return plcAddress;
        }

        public void setPlcAddress(String plcAddress) {
            this.plcAddress = plcAddress;
        }

        public Boolean getRequired() {
            return isRequired;
        }

        public void setRequired(Boolean required) {
            isRequired = required;
        }
    }

    // Helper method to get length for selected PLC data type
    private static int getLengthForDataType(String selectedType, String[] plcDataTypes, int[] dataTypeLengths) {
        for (int i = 0; i < plcDataTypes.length; i++) {
            if (plcDataTypes[i].equals(selectedType)) {
                return dataTypeLengths[i];
            }
        }
        return 0; // Default value or error handling if not found
    }

    // Custom cell renderer to display length based on selection in PLC Data Type column
    static class LengthCellRenderer extends DefaultTableCellRenderer {
        private Map<String, Integer> dataTypeLengthsMap;

        public LengthCellRenderer(String[] plcDataTypes, int[] dataTypeLengths) {
            dataTypeLengthsMap = new HashMap<>();
            for (int i = 0; i < plcDataTypes.length; i++) {
                dataTypeLengthsMap.put(plcDataTypes[i], dataTypeLengths[i]);
            }
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus, int row, int column) {
            Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            String dataType = (String) table.getValueAt(row, 4); // Get PLC Data Type value
            if (dataType != null && dataTypeLengthsMap.containsKey(dataType)) {
                setText(String.valueOf(dataTypeLengthsMap.get(dataType))); // Set length value
            } else {
                setText(""); // Handle case where no data type selected
            }
            return cellComponent;
        }
    }


}




